package com.atguigu.gmall.service;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.entity.GmallCorrelationData;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.CachedIntrospectionResults;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.UUID;

/**
 * @author ：MJS
 * @date ：Created in 2021/5/26  19:54
 * @description：TODO
 */
@Component
@SuppressWarnings("all")
public class RabbitService {
    @Autowired
    private RabbitTemplate rabbitTemplate;  //客户端  生产者
    @Autowired
    private RedisTemplate redisTemplate;

    //发普通消息
    public boolean sendMessage(String exchange, String routingKey, Object msg) {
        //回调对象  目标为了发消息失败应答以后 重新发送所需要的对象
        GmallCorrelationData correlationData = new GmallCorrelationData();
        //唯一  ID
        String uuid = UUID.randomUUID().toString().replace("-", "");
        correlationData.setId(uuid);//此id是唯一的
        System.out.println("uuid:" + uuid);
        //设置交换机
        correlationData.setExchange(exchange);
        //RoutingKey
        correlationData.setRoutingKey(routingKey);
        //消息
        correlationData.setMessage(msg);
        //外力 Redis
        String cacheKey = "mq:retry:message";
        redisTemplate.opsForHash().put(cacheKey, uuid, JSONObject.toJSONString(correlationData));//为队列应答失败使用,hv 需要转成json
        //发消息
        rabbitTemplate.convertAndSend(exchange, routingKey, msg, correlationData);//交换机应答失败
        return true;
    }

    //发送死信延迟消息
    public void sendDeadLetterMessage(String exchange, String routingKey, Object msg, int time) {
        //回调对象  目标为了发消息失败应答以后 重新发送所需要的对象
        GmallCorrelationData correlationData = new GmallCorrelationData();
        //唯一  ID
        String uuid = UUID.randomUUID().toString().replace("-", "");
        correlationData.setId(uuid);//此id是唯一的
        System.out.println("uuid:" + uuid);
        //设置交换机
        correlationData.setExchange(exchange);
        //RoutingKey
        correlationData.setRoutingKey(routingKey);
        //消息
        correlationData.setMessage(msg);
        //新增的下面两个
        //是延迟消息吗
        correlationData.setDelay(true);
        //延迟时间
        correlationData.setDelayTime(time);
        //外力 Redis
        String cacheKey = "mq:retry:message";
        redisTemplate.opsForHash().put(cacheKey, uuid, JSONObject.toJSONString(correlationData));//队列应答失败
        //发延迟消息 基于死信 过期 TTL
        rabbitTemplate.convertAndSend(exchange, routingKey, msg, message -> {
            //过期时间  毫秒
            System.out.println("发消息的时间：" + new Date());
            //过期时间 基于死信的  毫秒
            message.getMessageProperties().setExpiration(String.valueOf(time * 1000));
            //入参即为返回值
            return message;
        }, correlationData);
    }

    //基于插件的延迟消息
    public void sendDelayMessage(String exchange, String routingKey, Object msg, int time) {
        //回调对象  目标为了发消息失败应答以后 重新发送所需要的对象
        GmallCorrelationData correlationData = new GmallCorrelationData();
        //唯一  ID
        String uuid = UUID.randomUUID().toString().replace("-", "");
        correlationData.setId(uuid);//此id是唯一的
        System.out.println("uuid:" + uuid);
        //设置交换机
        correlationData.setExchange(exchange);
        //RoutingKey
        correlationData.setRoutingKey(routingKey);
        //消息
        correlationData.setMessage(msg);
        //新增的下面两个
        //是延迟消息吗
        correlationData.setDelay(true);
        //是插件的吗
        correlationData.setChaJian(true);
        //延迟时间
        correlationData.setDelayTime(time);
        //外力 Redis
        String cacheKey = "mq:retry:message";
        redisTemplate.opsForHash().put(cacheKey, uuid, JSONObject.toJSONString(correlationData));//队列应答失败
        //发延迟消息 基于插件
        rabbitTemplate.convertAndSend(exchange, routingKey, msg, message -> {
            //过期时间  毫秒
            System.out.println("基于插件发消息的时间：" + new Date());
            //过期时间 基于死信的  毫秒
            message.getMessageProperties().setDelay(time * 1000);
            //入参即为返回值
            return message;
        }, correlationData);
    }

}
